package com.sadhoc.router.topology;

import java.util.HashSet;

import java.util.Iterator;
import java.util.Set;

import com.sadhoc.router.Constants;
import com.sadhoc.router.pdu.TCMsg;
import com.sadhoc.router.util.ExpiringHashMap;

public class TopologyTable extends ExpiringHashMap<NodePair, TopologyTableEntry> {

	private static final long serialVersionUID = 574346864703472650L;
			
	public void handleTCMsg(String originator, TCMsg tcMsg) {
		
		SequenceNumber sequenceNumber = tcMsg.getSequenceNumber();
		HashSet<String> advertisedNodes = tcMsg.getNodes();
		
		synchronized(super.getLock()) {
		
			// Remove any old entries
			boolean changed = false;
			Set<NodePair> set = keySet();
		    Iterator<NodePair> itr = set.iterator(); 
		    while (itr.hasNext()) 
		    { 
	        	NodePair key = itr.next();
	        	if (key.getOriginator().equals(originator)) {
	        		SequenceNumber s = getEntry(key).getSequenceNumber();
	        		if (s.compare(sequenceNumber) < 0) {
	        			itr.remove();
	        			removeEntry(key);
	        			changed = true;
	        		}
	        	}
		    }
			
		    // Add or update any new entries
			for (String node : advertisedNodes) {
				NodePair pair = new NodePair(originator, node);
				TopologyTableEntry t = getEntry(pair);
				if (t == null) {
					changed = true;
				}
				addEntry(pair, new TopologyTableEntry(originator, node, sequenceNumber), Constants.TOPOLOGY_VALID_TIME);
				
			}
			
		    if (changed) setChangedFlag(true);
			
		}		
		
	}
	
	public void removeEntriesFromOriginator(String originator) {
		
		synchronized(super.getLock()) {
			
			for (NodePair pair : getCopyOfAllData().keySet()) {
				if (pair.getOriginator().equals(originator)) {
					removeEntry(pair);
					this.setChangedFlag(true);
				}
			}
		}
		
	}
	
	public String toString() {
		String s = "Originator           \tADV Node\tSeq#\n";
		s += "-----------\t--------\t------\n";
	
		synchronized(getLock()) {
			Set<NodePair> set = keySet();
		    Iterator<NodePair> itr = set.iterator(); 
		    while (itr.hasNext()) 
		    { 
		    	NodePair key = itr.next();
		    	s += key.getOriginator() + "\t" + key.getAdvertisedNode() + "\t" + getEntry(key).getSequenceNumber().getSeqNum() +"\n";
		    }
		    if (set.size() <= 0) 
		    	s += "No entries";
			
			return s;
		}
	}
	
	public TopologyTable clone() {
		
		TopologyTable table = new TopologyTable(); 
		synchronized(super.getLock()) {
			for (NodePair pair : keySet()) {
				table.addEntry(pair, getEntry(pair), 0);
			}
		}
		
		return table;
		
	}
	
	public void onRemoved(NodePair key) {
		
	}


}
